package com.zf.yichat.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSONArray;
import com.github.pagehelper.PageHelper;
import com.zf.yichat.dto.StTicketDto;
import com.zf.yichat.dto.TicketMarketDto;
import com.zf.yichat.dto.TicketsDto;
import com.zf.yichat.mapper.*;
import com.zf.yichat.model.*;
import com.zf.yichat.service.BalanceService;
import com.zf.yichat.service.SysDictService;
import com.zf.yichat.service.TicketsService;
import com.zf.yichat.utils.YiChatMsgCode;
import com.zf.yichat.utils.common.FsConst;
import com.zf.yichat.utils.common.N3d;
import com.zf.yichat.utils.response.FsResponse;
import com.zf.yichat.utils.response.FsResponseGen;
import com.zf.yichat.vo.BalanceType;
import com.zf.yichat.vo.DictKey;
import org.hibernate.validator.internal.util.Contracts;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

@Service
public class TicketsServiceImpl implements TicketsService {

    @Autowired
    private SysDictService sysDictService;

    @Resource
    private StUserTicketMapper userTicketMapper;
    @Resource
    private StOfficialTicketMapper officialTicketMapper;
    @Resource
    private UserMapper userMapper;
    @Resource
    private StTicketMarketMapper ticketMarketMapper;
    @Resource
    private StTicketTransactionRecordMapper ticketTransactionRecordMapper;

    @Autowired
    private BalanceService balanceService;

    @Override
    public int giveUserTickets(Long userId) {

        Example example = new Example(StUserTicket.class);
        example.createCriteria().andEqualTo("userId", userId).andEqualTo("ticketType", StUserTicket.TYPE_REGISTER);
        List<StUserTicket> list = userTicketMapper.selectByExample(example);
        if (null != list && list.size() > 0) {
            return 0;
        }

        StUserTicket ticket = new StUserTicket();
        ticket.setTicketType(StUserTicket.TYPE_REGISTER);
        ticket.setStatus(StUserTicket.STATUS_ACTIVATION_NO);
        ticket.setUserId(userId);
        ticket.setCreateTime(new Date());
        ticket.setTicketCode(IdUtil.simpleUUID());

        return  userTicketMapper.insertSelective(ticket);
    }

    @Override
    public List<StUserTicket> queryUserTickets(Long userId, Integer status) {

        Example example = new Example(StUserTicket.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("userId", userId);
        if (null != status) {
            criteria.andEqualTo("status", status);
        }
        List<StUserTicket> list = userTicketMapper.selectByExample(example);
        return list;
    }

    @Override
    public FsResponse activateUserTickets(Long adminUserId, String ticketCode, Long userId) {

        User activationUser = userMapper.queryUserByParam("", adminUserId);
        // 判断激活用户是否门票管理员
        String admins = Optional.ofNullable(sysDictService.selectOne(DictKey.sys_dict_ticket_admin)).map(SysDict::getMemo).orElse(null);
        if(admins == null){
            return FsResponseGen.failMsg("无激活权限");
        }
        if(!admins.contains(adminUserId.toString())){
            return FsResponseGen.failMsg("无激活权限");
        }

        // 判断该门票是否已激活
        StUserTicket userTicket = userTicketMapper.queryUserTicketByCode(userId, ticketCode);
        if (null == userTicket) {
            return FsResponseGen.failMsg("门票不存在！");
        }

        Integer status = userTicket.getStatus();
        if (StUserTicket.STATUS_ACTIVATION_YES.equals(status)) {
            return FsResponseGen.failMsg("门票已激活，无需重复激活！");
        }

        Long ticketUserId = userTicket.getUserId();
        User ticketUser = userMapper.queryUserByParam("", ticketUserId);
        if (null == ticketUser) {
            return FsResponseGen.failMsg("门票持有者不存在！");
        }

        String remark = activationUser.getNick() + "于" + DateUtil.today() + "激活" + ticketUser.getNick() + "的门票";

        StUserTicket ticket = new StUserTicket();
        ticket.setId(userTicket.getId());
        ticket.setStatus(StUserTicket.STATUS_ACTIVATION_YES);
        ticket.setActivationTime(new Date());
        ticket.setActivationUser(activationUser.getNick());
        ticket.setRemark(remark);
        userTicketMapper.updateByPrimaryKeySelective(ticket);
        return FsResponseGen.successMsg(remark);
    }

    @Override
    public FsResponse officialInvitationTickets(Long userId, String ticketCode) {

        // 查询官方配置的有效门票
        Example example = new Example(StOfficialTicket.class);
        example.createCriteria().andEqualTo("status", FsConst.Status.EFFECT).andEqualTo("ticketCode", ticketCode);
        StOfficialTicket officialTicket = officialTicketMapper.selectOneByExample(example);
        if (null == officialTicket) {
            return FsResponseGen.failMsg("抱歉，该门票码不存在！");
        }

        Integer status = officialTicket.getStatus();
        if (FsConst.Status.INVALID == status) {
            return FsResponseGen.failMsg("抱歉，该门票码已失效！");
        }

        // 根据后台配置的有效天数和有效次数来判断本次邀请是否生效
        Example exampleUserTicket = new Example(StUserTicket.class);
        exampleUserTicket.createCriteria().andEqualTo("ticketCode", ticketCode).andEqualTo("ticketType", StUserTicket.TYPE_OFFICIAL);
        List<StUserTicket> userTickets = userTicketMapper.selectByExample(exampleUserTicket);

        Integer scanCount = officialTicket.getScanCount();
        Integer scannedCount = userTickets.size();

        // 已扫描次数大于等于可扫描次数
        if (scannedCount >= scanCount){
            StOfficialTicket ticket = new StOfficialTicket();
            ticket.setId(officialTicket.getId());
            ticket.setStatus(FsConst.Status.INVALID);
            officialTicketMapper.updateByPrimaryKeySelective(ticket);
            return FsResponseGen.failMsg("抱歉，该门票码已失效，【可用次数不足】！");
        }

        // 日期是否失效

        // 有效天数
        Integer validDays = officialTicket.getValidDays();
        // 开始有效时间
        Date startDate = officialTicket.getStartDate();
        Date effectiveTime = DateUtil.offsetDay(startDate, validDays);

        Date nowDate = DateUtil.date();
        if (nowDate.after(effectiveTime)) {
            StOfficialTicket ticket = new StOfficialTicket();
            ticket.setId(officialTicket.getId());
            ticket.setStatus(FsConst.Status.INVALID);
            officialTicketMapper.updateByPrimaryKeySelective(ticket);
            return FsResponseGen.failMsg("抱歉，该门票码已失效，【日期过期】！");
        }

        // 判断用户是否已领取门票
        StUserTicket ticket = userTicketMapper.queryUserTicketByCode(userId, ticketCode);
        if (null != ticket) {
            return FsResponseGen.failMsg("您已领取门票！");
        }


        // 新增官方类型 用户门票
        StUserTicket userTicket = new StUserTicket();
        userTicket.setTicketType(StUserTicket.TYPE_OFFICIAL);
        userTicket.setStatus(StUserTicket.STATUS_ACTIVATION_NO);
        userTicket.setUserId(userId);
        userTicket.setCreateTime(new Date());
        userTicket.setTicketCode(ticketCode);
        return FsResponseGen.successData(userTicketMapper.insertSelective(userTicket));
    }

    @Override
    public List<StTicketDto> queryUserScanCode(String ticketCode) {
        Example example = new Example(StUserTicket.class);
        example.createCriteria().andEqualTo("ticketCode", ticketCode).andEqualTo("ticketType", StUserTicket.TYPE_OFFICIAL);
        List<StUserTicket> list = userTicketMapper.selectByExample(example);

        ArrayList<StTicketDto> stTicketList = new ArrayList<>();
        for (StUserTicket ticket : list) {
            StTicketDto stTicketDto = new StTicketDto();
            BeanUtils.copyProperties(ticket, stTicketDto);
            Long userId = ticket.getUserId();
            User user = userMapper.queryUserByParam("", userId);
            if (null != user) {
                stTicketDto.setNick(user.getNick());
                stTicketDto.setAvatar(user.getAvatar());
            }
            stTicketList.add(stTicketDto);
        }
        return stTicketList;
    }

    @Override
    public List<TicketMarketDto> queryTicketMarketList(Integer showType, Long userId) throws Exception {

        Example example = new Example(StTicketMarket.class);
        if (null == showType || showType == 0) {
            example.createCriteria().andEqualTo("status", StTicketMarket.STATUS_LISTED)
                    .andNotEqualTo("userId", userId);
        }
        if (null != showType && showType == 1) {
            example.createCriteria().andEqualTo("userId", userId).andCondition("status in ('0','2')");
        }
        example.setOrderByClause(" on_sale_time desc");
        List<StTicketMarket> list = ticketMarketMapper.selectByExample(example);
        ArrayList<TicketMarketDto> ticketMarketDtos = new ArrayList<TicketMarketDto>();
        for (StTicketMarket market : list) {
            TicketMarketDto marketDto = new TicketMarketDto();
            BeanUtils.copyProperties(market, marketDto);

            TicketsDto ticketInfo = userTicketMapper.queryUserTicketInfo(market.getUserTicketId());
            marketDto.setTicket(ticketInfo);

            String encodeUserId = N3d.encode(market.getUserId());
            marketDto.setUserId(encodeUserId);

            // 如果是市场列表，status设置为3 代表立即购买
            if (null == showType || showType == 0) {
                marketDto.setStatus(StTicketMarket.STATUS_BUY);
            }
            ticketMarketDtos.add(marketDto);
        }

        return ticketMarketDtos;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FsResponse ticketListing(Long userId, Integer ticketId, BigDecimal ticketPrice, String ticketTitle) {
        User user = userMapper.queryUserByParam("", userId);
        if (null == user) {
            return FsResponseGen.failMsg("用户不存在，userId: " + userId);
        }

        // 判断门票是否已激活
        StUserTicket ticket = userTicketMapper.selectByPrimaryKey(ticketId);
        if (null == ticket) {
            return FsResponseGen.failMsg("门票不存在！");
        }
        if (!ticket.getUserId().toString().equals(userId.toString())) {
            return FsResponseGen.failMsg("该门票归属有误，暂无法上架！");
        }
        if (null != ticket && StUserTicket.STATUS_ACTIVATION_NO.equals(ticket.getStatus())) {
            return FsResponseGen.failMsg("门票未激活！");
        }

        Example example = new Example(StTicketMarket.class);
        example.createCriteria().andEqualTo("userTicketId", ticketId).andEqualTo("userId", userId);
        StTicketMarket ticketMarket = ticketMarketMapper.selectOneByExample(example);
        if (null != ticketMarket) {
            Integer marketStatus = ticketMarket.getStatus();
            if (StTicketMarket.STATUS_LISTED.equals(marketStatus)) {
                return FsResponseGen.failMsg("门票已上架，无需重复！");
            }

            if (StTicketMarket.STATUS_REMOVED.equals(marketStatus)) {
                StTicketMarket market = new StTicketMarket();
                market.setId(ticketMarket.getId());
                market.setUserId(userId);
                market.setUserTicketId(ticketId);
                market.setUserNick(user.getNick());
                market.setUserAvatar(user.getAvatar());
                market.setTicketTitle(ticketTitle);
                market.setTicketPrice(ticketPrice);
                market.setStatus(StTicketMarket.STATUS_LISTED);
                market.setOnSaleTime(new Date());
                ticketMarketMapper.updateByPrimaryKeySelective(market);
                return FsResponseGen.successData("上架成功！");
            }
        }

        StTicketMarket market = new StTicketMarket();
        market.setUserId(userId);
        market.setUserTicketId(ticketId);
        market.setUserNick(user.getNick());
        market.setUserAvatar(user.getAvatar());
        market.setTicketTitle(ticketTitle);
        market.setTicketPrice(ticketPrice);
        market.setStatus(StTicketMarket.STATUS_LISTED);
        market.setOnSaleTime(new Date());
        ticketMarketMapper.insertSelective(market);
        return FsResponseGen.successData("上架成功！");
    }

    @Override
    public FsResponse ticketEdit(Integer marketId, BigDecimal ticketPrice, String ticketTitle, Integer ticketStatus) {

        StTicketMarket market = new StTicketMarket();
        market.setId(marketId);
        market.setTicketPrice(ticketPrice);
        market.setTicketTitle(ticketTitle);
        if (null != ticketStatus) {
            market.setStatus(ticketStatus);
            if (StTicketMarket.STATUS_REMOVED.equals(ticketStatus)) {
                market.setOffSaleTime(new Date());
            }
        }
        ticketMarketMapper.updateByPrimaryKeySelective(market);
        return FsResponseGen.successData("操作成功！");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FsResponse ticketPurchase(Long userId, String ownerId, Integer marketId) {

        StTicketMarket market = ticketMarketMapper.selectByPrimaryKey(marketId);
        if (null == market) {
            return FsResponseGen.failMsg("市场门票不存在: ID：" + marketId);
        }

        Integer status = market.getStatus();
        if (StTicketMarket.STATUS_REMOVED == status) {
            return FsResponseGen.failMsg("该门票已下架: ID：" + marketId);
        }
        if (StTicketMarket.STATUS_SOLD == status) {
            return FsResponseGen.failMsg("该门票已出售: ID：" + marketId);
        }

        Long decodeOwnerId = null;
        try {
            decodeOwnerId = N3d.decode(ownerId);
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (decodeOwnerId.toString().equals(userId.toString())) {
            return FsResponseGen.failMsg("您已有该门票，无需购买！");
        }


        //  TODO  是否需要判断用户门票是否失效  暂时不处理

        //  将用户门票信息改成购买者的信息
        Integer userTicketId = market.getUserTicketId();
        StUserTicket ticket = userTicketMapper.selectByPrimaryKey(userTicketId);
        if (null == ticket) {
            return FsResponseGen.failMsg("用户门票不存在: ID" + userTicketId);
        }

        StUserTicket updateUserTicket = new StUserTicket();
        updateUserTicket.setId(userTicketId);
        updateUserTicket.setUserId(userId);
        userTicketMapper.updateByPrimaryKeySelective(updateUserTicket);

        //  修改买卖双方的余额记录

        BigDecimal ticketPrice = market.getTicketPrice();
        // 查询购买者得余额是否充足
        UserBalance balance = balanceService.selectByUserId(userId);
        Contracts.assertTrue(balance.getIncomeBalance().compareTo(ticketPrice) >= 0, YiChatMsgCode.PACKET_CREATE_NO_ENOUGH_BALANCE.msg());

        // 更新购买用户余额
        balanceService.update(userId, BalanceType.USERS_PURCHASE_TICKETS, ticketPrice, userId, BalanceType.USERS_PURCHASE_TICKETS.getDesc());

        // 更新出售用户金额
        balanceService.update(decodeOwnerId, BalanceType.USERS_SELLING_TICKETS, ticketPrice, decodeOwnerId, BalanceType.USERS_SELLING_TICKETS.getDesc());

        //  修改市场门票状态为已出售
        StTicketMarket updateMarket = new StTicketMarket();
        // 更新为购买者信息
        User user = userMapper.queryUserByParam("", userId);
        updateMarket.setUserId(userId);
        updateMarket.setUserNick(user.getNick());
        updateMarket.setUserAvatar(user.getAvatar());
        updateMarket.setId(marketId);
        updateMarket.setStatus(StTicketMarket.STATUS_SOLD);
        updateMarket.setSoldTime(new Date());
        ticketMarketMapper.updateByPrimaryKeySelective(updateMarket);

        // 买卖记录
        StTicketTransactionRecord record = new StTicketTransactionRecord();
        record.setTicketId(userTicketId);
        record.setMarketTicketId(marketId);
        record.setSellerId(decodeOwnerId);
        record.setBuyerId(userId);
        record.setCreateTime(new Date());
        ticketTransactionRecordMapper.insertSelective(record);
        return FsResponseGen.successData("购买成功！");
    }

    @Override
    public FsResponse ticketRecord(Long userId, Integer recordStatus, Integer pageNo, Integer pageSize) throws Exception {


        Example example = new Example(StTicketTransactionRecord.class);
        Example.Criteria criteria = example.createCriteria();
        // 已购买
        if (0 == recordStatus) {
            criteria.andEqualTo("buyerId", userId);
        }
        if (1 == recordStatus) {
            criteria.andEqualTo("sellerId", userId);
        }
        PageHelper.startPage(pageNo, pageSize);
        List<StTicketTransactionRecord> recordList = ticketTransactionRecordMapper.selectByExample(example);

        ArrayList<TicketMarketDto> ticketMarketDtos = new ArrayList<TicketMarketDto>();
        for (StTicketTransactionRecord record : recordList) {
            Integer marketTicketId = record.getMarketTicketId();
            StTicketMarket market = ticketMarketMapper.selectByPrimaryKey(marketTicketId);

            TicketMarketDto marketDto = new TicketMarketDto();
            BeanUtils.copyProperties(market, marketDto);

            TicketsDto ticketInfo = userTicketMapper.queryUserTicketInfo(marketTicketId);
            marketDto.setTicket(ticketInfo);

            String encodeUserId = N3d.encode(market.getUserId());
            marketDto.setUserId(encodeUserId);
            ticketMarketDtos.add(marketDto);
        }
        return FsResponseGen.successData(ticketMarketDtos);
    }


}
